﻿using PmSoft.Core;
using System.Runtime.CompilerServices;

namespace PmSoft.Core.Extensions;

public static class CheckExtensions
{
	/// <summary>
	/// 检查值是否为 null
	/// </summary>
	/// <typeparam name="T">值的类型</typeparam>
	/// <param name="value">要检查的值</param>
	/// <param name="name">调用成员的名称</param>
	/// <returns>非 null 的值</returns>
	/// <exception cref="ArgumentNullException">如果值为 null，则抛出异常</exception>
	public static T NotNull<T>(this T value, [CallerMemberName] string? name = null)
	{
		if (value == null) throw new ArgumentNullException(name);
		return value;
	}

	/// <summary>
	/// 检查值是否为 null，并提供自定义错误消息
	/// </summary>
	/// <typeparam name="T">值的类型</typeparam>
	/// <param name="value">要检查的值</param>
	/// <param name="message">自定义错误消息</param>
	/// <param name="name">调用成员的名称</param>
	/// <returns>非 null 的值</returns>
	/// <exception cref="ArgumentNullException">如果值为 null，则抛出异常</exception>
	public static T NotNull<T>(this T value, string message, [CallerMemberName] string? name = null)
	{
		if (value == null) throw new ArgumentNullException(name, message);
		return value;
	}

	/// <summary>
	/// 检查列表是否为空
	/// </summary>
	/// <typeparam name="T">列表中元素的类型</typeparam>
	/// <param name="value">要检查的列表</param>
	/// <param name="name">调用成员的名称</param>
	/// <returns>非空的列表</returns>
	/// <exception cref="ArgumentException">如果列表为空，则抛出异常</exception>
	public static IReadOnlyList<T> NotEmpty<T>(this IReadOnlyList<T> value, [CallerMemberName] string? name = null)
	{
		if (value.Count == 0) throw new ArgumentException($"{name} 不能为空");
		return value;
	}

	/// <summary>
	/// 根据条件抛出自定义异常
	/// </summary>
	/// <typeparam name="T">值的类型</typeparam>
	/// <param name="value">要检查的值</param>
	/// <param name="predicate">条件谓词</param>
	/// <param name="exception">要抛出的自定义异常</param>
	public static void ThrowIf<T>(this T value, Func<T, bool> predicate, PmSoftException exception)
	{
		if (predicate(value)) throw exception;
	}
}
